﻿using System;

using DDDSample.Common.Validate;
using DDDSample.Domain.Model.Locations;

namespace DDDSample.Domain.Model.Cargos
{
	/// <summary>
	/// Route specification.
	/// </summary>
	public class RouteSpecification : ValueObject<RouteSpecification>, ISpecification<Itinerary>
	{
		private Location origin;
		private Location destination;
		private DateTime arrivalDeadline;

		/// <summary>
		/// Factory for creatig a route specification for a cargo, from cargo
		/// origin to cargo destination. Use for initial routing.
		/// </summary>
		/// <param name="cargo">cargo</param>
		/// <param name="arrivalDeadline">arrival deadline</param>
		/// <returns>A route specification for this cargo and arrival deadline</returns>
		public static RouteSpecification ForCargo(Cargo cargo, DateTime arrivalDeadline)
		{
			Validate.NotNull(cargo);

			return new RouteSpecification(cargo.Origin, cargo.Destination, arrivalDeadline);
		}

		private RouteSpecification(Location origin, Location destination, DateTime arrivalDeadline)
		{
			this.origin = origin;
			this.destination = destination;
			this.arrivalDeadline = arrivalDeadline;
		}

		public Location Origin
		{
			get { return this.origin; }
		}

		public Location Destination
		{
			get { return this.destination; }
		}

		public bool IsSatisfiedBy(Itinerary itinerary)
		{
			// Stub implementation for now
			return true;
		}

		public override bool SameValueAs(RouteSpecification other)
		{
			return other != null &&
				this.origin.Equals(other.origin) &&
				this.destination.Equals(other.destination) &&
				this.arrivalDeadline.Equals(other.arrivalDeadline);
		}

		public override bool Equals(object obj)
		{
			if (this == obj) return true;
			if (obj == null || GetType() != obj.GetType()) return false;

			RouteSpecification other = (RouteSpecification)obj;

			return SameValueAs(other);
		}

		public override int GetHashCode()
		{
			int hashCode = 37 + this.origin.GetHashCode();
			hashCode = hashCode * 17 + this.destination.GetHashCode();
			hashCode = hashCode * 17 + this.arrivalDeadline.GetHashCode();
			return hashCode;
		}
	}
}
